
#ifndef __HTTP_STATUS_H__
#define __HTTP_STATUS_H__

#include <string>
#include <map>

namespace HTTP {
namespace Status {


const std::string   RC_CONTINUE                          ("100");
const std::string   RC_SWITCHING_PROTOCOLS               ("101");
const std::string   RC_PROCESSING                        ("102");

const std::string   RC_OK                                ("200");
const std::string   RC_CREATED                           ("201");
const std::string   RC_ACCEPTED                          ("202");
const std::string   RC_NON_AUTHORITATIVE_INFORMATION     ("203");
const std::string   RC_NO_CONTENT                        ("204");
const std::string   RC_RESET_CONTENT                     ("205");
const std::string   RC_PARTIAL_CONTENT                   ("206");
const std::string   RC_MULTI_STATUS                      ("207");

const std::string   RC_MULTIPLE_CHOICES                  ("300");
const std::string   RC_MOVED_PERMANENTLY                 ("301");
const std::string   RC_FOUND                             ("302");
const std::string   RC_SEE_OTHER                         ("303");
const std::string   RC_NOT_MODIFIED                      ("304");
const std::string   RC_USE_PROXY                         ("305");
const std::string   RC_TEMPORARY_REDIRECT                ("307");

const std::string   RC_BAD_REQUEST                       ("400");
const std::string   RC_UNAUTHORIZED                      ("401");
const std::string   RC_PAYMENT_REQUIRED                  ("402");
const std::string   RC_FORBIDDEN                         ("403");
const std::string   RC_NOT_FOUND                         ("404");
const std::string   RC_METHOD_NOT_ALLOWED                ("405");
const std::string   RC_NOT_ACCEPTABLE                    ("406");
const std::string   RC_PROXY_AUTHENTICATION_REQUIRED     ("407");
const std::string   RC_REQUEST_TIMEOUT                   ("408");
const std::string   RC_CONFLICT                          ("409");
const std::string   RC_GONE                              ("410");
const std::string   RC_LENGTH_REQUIRED                   ("411");
const std::string   RC_PRECONDITION_FAILED               ("412");
const std::string   RC_REQUEST_ENTITY_TOO_LARGE          ("413");
const std::string   RC_REQUEST_URI_TOO_LARGE             ("414");
const std::string   RC_UNSUPPORTED_MEDIA_TYPE            ("415");
const std::string   RC_REQUEST_RANGE_NOT_SATISFIABLE     ("416");
const std::string   RC_EXPECTATION_FAILED                ("417");
const std::string   RC_UNPROCESSABLE_ENTITY              ("422");
const std::string   RC_LOCKED                            ("423");
const std::string   RC_FAILED_DEPENDENCY                 ("424");

const std::string   RC_INTERNAL_SERVER_ERROR             ("500");
const std::string   RC_NOT_IMPLEMENTED                   ("501");
const std::string   RC_BAD_GATEWAY                       ("502");
const std::string   RC_SERVICE_UNAVAILABLE               ("503");
const std::string   RC_GATEWAY_TIMEOUT                   ("504");
const std::string   RC_HTTP_VERSION_NOT_SUPPORTED        ("505");
const std::string   RC_INSUFFICIENT_STORAGE              ("507");

class StatusCollection
{
public:
	StatusCollection()
	{
		CODES["100"] = "Continue";
		CODES["101"] = "Switching Protocols";
		CODES["200"] = "OK";
		CODES["201"] = "Created";
		CODES["202"] = "Accepted";
		CODES["203"] = "Non-Authoritative Information";
		CODES["204"] = "No Content";
		CODES["205"] = "Reset Content";
		CODES["206"] = "Partial Content";
		CODES["300"] = "Multiple Choices";
		CODES["301"] = "Moved Permanently";
		CODES["302"] = "Found";
		CODES["303"] = "See Other";
		CODES["304"] = "Not Modified";
		CODES["305"] = "Use Proxy";
		CODES["307"] = "Temporary Redirect";
		CODES["400"] = "Bad Request";
		CODES["401"] = "Unauthorized";
		CODES["402"] = "Payment Required";
		CODES["403"] = "Forbidden";
		CODES["404"] = "Not Found";
		CODES["405"] = "Method Not Allowed";
		CODES["406"] = "Not Acceptable";

		CODES["407"] = "Proxy Authentication Required";
		CODES["408"] = "Request Time-out";
		CODES["409"] = "Conflict";
		CODES["410"] = "Gone";
		CODES["411"] = "Length Required";
		CODES["412"] = "Precondition Failed";
		CODES["413"] = "Request Entity Too Large";
		CODES["414"] = "Request-URI Too Large";
		CODES["415"] = "Unsupported Media Type";
		CODES["416"] = "Requested range not satisfiable";
		CODES["417"] = "Expectation Failed";
		CODES["500"] = "Internal Server Error";
		CODES["501"] = "Not Implemented";
		CODES["502"] = "Bad Gateway";
		CODES["503"] = "Service Unavailable";
		CODES["504"] = "Gateway Time-out";
		CODES["505"] = "HTTP Version not supported";
	}
	
	// Bad code
	// Is it a const function?
	std::string get(const std::string& code)
	{
		return CODES[code];
	}
private:
	std::map<std::string, std::string> CODES;
};

/*
std::map<std::string, std::string> init_codes()
{
	std::map<std::string, std::string> CODES;
	CODES["100"] = "Continue";
	CODES["101"] = "Switching Protocols";
	CODES["200"] = "OK";
	CODES["201"] = "Created";
	CODES["202"] = "Accepted";
	CODES["203"] = "Non-Authoritative Information";
	CODES["204"] = "No Content";
	CODES["205"] = "Reset Content";
	CODES["206"] = "Partial Content";
	CODES["300"] = "Multiple Choices";
	CODES["301"] = "Moved Permanently";
	CODES["302"] = "Found";
	CODES["303"] = "See Other";
	CODES["304"] = "Not Modified";
	CODES["305"] = "Use Proxy";
	CODES["307"] = "Temporary Redirect";
	CODES["400"] = "Bad Request";
	CODES["401"] = "Unauthorized";
	CODES["402"] = "Payment Required";
	CODES["403"] = "Forbidden";
	CODES["404"] = "Not Found";
	CODES["405"] = "Method Not Allowed";
	CODES["406"] = "Not Acceptable";

	CODES["407"] = "Proxy Authentication Required";
	CODES["408"] = "Request Time-out";
	CODES["409"] = "Conflict";
	CODES["410"] = "Gone";
	CODES["411"] = "Length Required";
	CODES["412"] = "Precondition Failed";
	CODES["413"] = "Request Entity Too Large";
	CODES["414"] = "Request-URI Too Large";
	CODES["415"] = "Unsupported Media Type";
	CODES["416"] = "Requested range not satisfiable";
	CODES["417"] = "Expectation Failed";
	CODES["500"] = "Internal Server Error";
	CODES["501"] = "Not Implemented";
	CODES["502"] = "Bad Gateway";
	CODES["503"] = "Service Unavailable";
	CODES["504"] = "Gateway Time-out";
	CODES["505"] = "HTTP Version not supported";

	return CODES;
}

std::map<std::string, std::string> STATUS_CODES = init_codes();
*/

std::string status_message(const std::string& code)
{
//	return STATUS_CODES[code];
	static StatusCollection STATUS_CODES;
	return STATUS_CODES.get(code);
}

bool is_code(const std::string& code)
{
	if(code.length()!=3)
		return false;
	return '0'<=code[0] && code[0]<='9'
	    && '0'<=code[1] && code[1]<='9'
	    && '0'<=code[2] && code[2]<='9';
}

// Note
// Not check if the code is a number

bool is_info(std::string code)
{
	return code.length()==3 && code[0]=='1';
}

bool is_success(std::string code)
{
	return code.length()==3 && code[0]=='2';
}

bool is_redirect(std::string code)
{
	return code.length()==3 && code[0]=='3';
}

bool is_error(std::string code)
{
	return code.length()==3 && (code[0]=='4' || code[0]=='5');
}

bool is_client_error(std::string code)
{
	return code.length()==3 && code[0]=='4';
}

bool is_server_error(std::string code)
{
	return code.length()==3 && code[0]=='5';
}



}//end HTTP::Status
}//end HTTP

#endif
